package com.octopus.file;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.log4j.Logger;

import com.octopus.string.StringUtils;

public class FileUtils {
	
	private final static Logger logger = Logger.getLogger(FileUtils.class.getName());
	
	public static String fileContentToRightString(String absFilePath, String charset) throws IOException{
		File file = new File(absFilePath);
		return fileContentToRightString(file, charset);
	}
	
	public static String fileContentToRightString(File file, String charset) throws IOException{
		String result = null;
		if(file == null || (!file.exists()) || (!file.isFile())){
			throw new FileNotFoundException(file == null ? "NULL" : file.getAbsolutePath());
		}
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			result = StringUtils.inputStreamToRightString(fis, charset);
		} finally{
			if(fis != null){
				try{
					fis.close();
				}catch(Exception e){
					logger.warn(StringUtils.concat("When closing InputStream of file[",file.getAbsolutePath(),"]"), e);
				}
			}
		}
		return result;
	}
	
	public static boolean writeRightStringToFile(String content, String charset, File path, String fileName, boolean append, boolean autoCreatePath, boolean overWrite) throws IOException{
		if(charset == null){
			charset = "UTF-8";
		}
		ByteArrayInputStream bais = new ByteArrayInputStream(content.getBytes(charset));
		return writeInputStreamToFile(bais, path, fileName, append, autoCreatePath, overWrite);
	}
	
	public static boolean writeInputStreamToFile(InputStream is, File path, String fileName, boolean append, boolean autoCreatePath, boolean overWrite) throws IOException{
		if(is == null || path == null || StringUtils.isNullString(fileName)){
			return false;
		}
		if(!path.exists()){
			if(autoCreatePath){
				boolean mkdirreesult = mkdirs(path);
				if(!mkdirreesult){
					//throw new IOException(StringUtils.concat("mkdirs [",path.getAbsolutePath(),"] failed"));
					return false;
				}
			}else{
				//throw new IOException(StringUtils.concat("Path [",path.getAbsolutePath(),"] doesn't exist"));
				return false;
			}
		}
		byte[] buffer = new byte[65536];
		FileOutputStream fos = null;
		try{
			File writeFile = new File(path, fileName);
			if(writeFile.exists() && !overWrite){
				return false;
			}
			fos = new FileOutputStream(writeFile, append);
			int count = is.read(buffer);
			while(count > 0){
				fos.write(buffer, 0, count);
				fos.flush();
				count = is.read(buffer);
			}
		}finally{
			if(fos != null){
				try{
					fos.close();
				}catch(Exception e){
					logger.warn("When close OutputStream", e);
				}
			}
		}
		return true;
	}
	
	public static boolean mkdir(String absPath) throws IOException{
		if(StringUtils.isNullString(absPath)){
			return false;
		}
		File file = new File(absPath);
		return mkdir(file);
	}
	
	public static boolean mkdirs(String absPath) throws IOException{
		if(StringUtils.isNullString(absPath)){
			return false;
		}
		File file = new File(absPath);
		return mkdirs(file);
	}
	
	public static boolean mkdirs(File file) throws IOException{
		if(file.exists() && file.isDirectory()){
			return true;
		}
		if(file.exists() && file.isFile()){
			throw new IOException(StringUtils.concat("file:[",file.getAbsolutePath(),"] is an exist file"));
		}
		if(!file.exists()){
			boolean result = file.mkdirs();
			if(result){
				if(!file.exists()){
					try{
						Thread.sleep(100);
					}catch(InterruptedException ie){
						logger.warn("After make dirs", ie);
					}
				}
				return file.exists();
			}else{
				return false;
			}
		}
		return false;
	}
	
	public static boolean mkdir(File file) throws IOException{
		if(file.exists() && file.isDirectory()){
			return true;
		}
		if(file.exists() && file.isFile()){
			throw new IOException(StringUtils.concat("file:[",file.getAbsolutePath(),"] is an exist file"));
		}
		if((!file.getParentFile().exists()) || !(file.getParentFile().isDirectory())){
			throw new IOException(StringUtils.concat("Parent [",file.getParentFile().getAbsolutePath(),"] doesn't exist"));
		}
		if(!file.exists()){
			boolean result = file.mkdir();
			if(result){
				if(!file.exists()){
					try{
						Thread.sleep(100);
					}catch(InterruptedException ie){
						logger.warn("After make dir", ie);
					}
				}
				return file.exists();
			}else{
				return false;
			}
		}
		return false;
	}
	
	public static String pickupFileName(String fileName){
		if(StringUtils.isNullString(fileName)){
			return "";
		}
		int slashIndex = fileName.lastIndexOf("/");
		int backSlashIndex = fileName.lastIndexOf("\\");
		int	lastSeparator = -1;
		if(slashIndex >= 0 && backSlashIndex < 0){
			lastSeparator = slashIndex;
		}else if(slashIndex < 0 && backSlashIndex >= 0 ){
			lastSeparator = backSlashIndex;
		}else if(slashIndex >= 0 && backSlashIndex >= 0){
			if(slashIndex >= backSlashIndex){
				lastSeparator = slashIndex;
			}else{
				lastSeparator = backSlashIndex;
			}
		}
		String realFileName = "";
		if(lastSeparator >= 0 && lastSeparator < fileName.length() - 1){
			realFileName = fileName.substring(lastSeparator+1);
		}else if(lastSeparator < 0){
			realFileName = fileName;
		}
		return realFileName.trim();
	}
	
	public static String[] separateFileNameIntoNameAndExt(String fileName){
		String[] result = new String[]{"",""};
		String rFileName = "";
		String rFileExt = "";
		String realFileName = pickupFileName(fileName);
		if(realFileName.length() == 0){
			return result;
		}else{
			int pointIndex = realFileName.lastIndexOf(".");
			if(pointIndex >= 0){
				if(pointIndex < realFileName.length() - 1){
					rFileExt = realFileName.substring(pointIndex+1);
					rFileName = realFileName.substring(0, pointIndex);
				}else{
					rFileName = realFileName;
				}
			}else if(pointIndex < 0){
				rFileName = realFileName;
			}
		}
		result[0] = rFileName;
		result[1] = rFileExt;
		return result;
	}
}
